package com.zx.onlineeducation.service.oss.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.comm.ResponseMessage;
import com.aliyun.oss.model.PutObjectResult;
import com.zx.onlineeducation.common.servicebase.exception.OnlineEducationException;
import com.zx.onlineeducation.common.util.ResultCodeEnum;
import com.zx.onlineeducation.service.oss.config.OSSProperties;
import com.zx.onlineeducation.service.oss.service.OssService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.UUID;

/**
 * Oss 服务实现类
 *
 * @author 郑雪
 * @since 2022-01-11
 */
@Service
@Slf4j
public class OssServiceImpl implements OssService {

    /**
     * 第三方OSS对象存储服务接口属性
     */
    @Autowired
    private OSSProperties ossProperties;

    /**
     * 上传文件到OSS服务器
     *
     * @param multipartFile 要上传的文件
     * @param folder 目标文件夹名称
     * @return 返回上传后的文件访问路径
     * @author 郑雪
     * @since 2022-01-11
     */
    @Override
    public String uploadFile(MultipartFile multipartFile, String folder) {

        // 生成OSSClient
        OSS ossClient = new OSSClientBuilder().build(ossProperties.getEndPoint(), ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());

        // 生成上传文件的目录
        String folderName = "files";
        if (!StringUtils.isEmpty(folder)) {
            folderName = folder;
        }

        // 生成上传文件在OSS服务器上保存时的文件名
        // 原始文件名：girl.jpg
        // 生成文件名：uuid.jpg
        // 使用UUID生成文件主体名称
        String fileMainName = UUID.randomUUID().toString().replace("-", "");

        // 上传文件的原始文件名
        String originalFileName = multipartFile.getOriginalFilename();

        assert originalFileName != null;

        // 从原始文件名中获取文件扩展名
        String extensionName = originalFileName.substring(originalFileName.lastIndexOf("."));

        // 使用目录、文件主体名称、文件扩展名称拼接得到对象名称
        String objectName = folderName + "/" + fileMainName + extensionName;

        try {

            // 调用OSS客户端对象的方法上传文件并获取响应结果数据
            PutObjectResult putObjectResult = ossClient.putObject(ossProperties.getBucketName(), objectName, multipartFile.getInputStream());

            // 从响应结果中获取具体响应消息
            ResponseMessage responseMessage = putObjectResult.getResponse();

            // 根据响应状态码判断请求是否成功
            if(responseMessage == null) {

                // 拼接访问刚刚上传的文件的路径
                String ossFileAccessPath = ossProperties.getBucketDomain() + "/" + objectName;

                // 打印日志
                log.info("文件：{}存入OSS成功。", objectName);

                // 返回文件访问路径
                return ossFileAccessPath;
            } else {
                // 获取响应状态码
                int statusCode = responseMessage.getStatusCode();

                // 如果请求没有成功，获取错误消息
                String errorMessage = responseMessage.getErrorResponseAsString();

                // 抛出系统异常
                throw new OnlineEducationException(statusCode, errorMessage);
            }

        } catch (Exception e) {
            e.printStackTrace();

            // 抛出系统异常
            throw new OnlineEducationException(ResultCodeEnum.FAILED);

        } finally {

            if(ossClient != null) {

                // 关闭OSSClient。
                ossClient.shutdown();
            }
        }
    }
}
